package com.csun.cmny.provider.device.card;

import com.csun.cmny.provider.device.card.entity.CardCmdEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-11-28 20:43
 * @Description:
 */
@Slf4j
public class CardMessageDecoder {

    /**
     * 解析数据
     *
     * @param data
     *
     * @return
     *
     * 数据格式
     *
     * -------------------------------------------------------------------------------------------------
     *  标志码 | 接收端代码 |    发送端信息     |          控制码       |        数据码      | 检验码 | 标志码
     * -------------------------------------------------------------------------------------------------
     *   7E   | 信息代码   |   设备SN | 密码  | 分类  |  命令  |  参数 | 数据长度 |   数据  | 检验值 | 7E
     * -------------------------------------------------------------------------------------------------
     *        |  4Byte    |  16Byte | 4Byte | 1Byte | 1Byte | 1Byte |  4Byte  | 可变长度 | 1Byte |
     * -------------------------------------------------------------------------------------------------
     */
    public static CardCmdEntity parse(byte[] data) {

        CardCmdEntity cardCmdEntity = new CardCmdEntity();

        byte tag = (byte) 0x7e;

        int length = data.length;

        if (tag != data[0] || tag != data[length - 1]) {
            log.warn("标志码错误 start = [{}], end = [{}]", byteTo16(data[0]), byteTo16(data[length - 1]));
            return null;
        }

        byte check = CardCmdEntity.getCheckSum(data, data.length);
        if (check != data[length - 2]) {
            log.warn("校验和错误 check = [{}], calc = [{}]", byteTo16(check), byteTo16(data[length - 2]));
            return null;
        }

        // 信息代码
        System.arraycopy(data, 1, cardCmdEntity.getCode(), 0, 4);
        // 设备SN
        System.arraycopy(data, 5, cardCmdEntity.getSn(), 0, 16);
        // 设备SN
        System.arraycopy(data, 21, cardCmdEntity.getPassword(), 0, 4);

        cardCmdEntity.setType(data[25]);

        cardCmdEntity.setCmd(data[26]);

        cardCmdEntity.setParam(data[27]);
        // 设备SN
        System.arraycopy(data, 28, cardCmdEntity.getLength(), 0, 4);
        int date_length = bytes2Int(cardCmdEntity.getLength()); // 长度
        if (length > 0) {
            cardCmdEntity.setData(new byte[date_length]);   // 初始化
            System.arraycopy(data, 32, cardCmdEntity.getData(), 0, date_length);
        }

        cardCmdEntity.setCheck(data[length - 2]);

        return cardCmdEntity;
    }

    public static String byteTo16(byte bt){

        String[] strHex= {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};

        String resStr= "";
        int low = (bt & 15);
        int high = bt>>4 & 15;
        resStr = strHex[high] + strHex[low];

        return resStr;
    }

    public static int bytes2Int(byte[] bytes) {

        int num=bytes[3] & 0xFF;
        num |=((bytes[2] <<8)& 0xFF00);
        num |=((bytes[1] <<16)& 0xFF0000);
        num |=((bytes[0] <<24)& 0xFF0000);
        return num;
    }
}
